package com.marvels.approve.process.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.druid.util.StringUtils;
import com.marvels.approve.common.service.McamLoanApplyInfoCommonService;
import com.marvels.approve.common.service.ProductConsumerService;
import com.marvels.approve.common.utils.InsuranceRateUtil;
import com.marvels.approve.consum.ApproveConsumerExternalApi;
import com.marvels.approve.consum.ApproveConsumerFinancialApi;
import com.marvels.approve.consum.ApproveConsumerProductApi;
import com.marvels.approve.consum.ApproveConsumerUmApi;
import com.marvels.approve.loan.dto.LoanAfterInfoDTO;
import com.marvels.approve.loan.dto.McamAcLoanApplyBdInfo;
import com.marvels.approve.loan.dto.McamAcLoanApplyImageInfo;
import com.marvels.approve.loan.dto.McamLoanApplyInfoDTO;
import com.marvels.approve.loan.dto.McptConsultingFeeDTO;
import com.marvels.approve.loan.dto.McptProductTypeDto;
import com.marvels.approve.loan.service.McamLoanInsurancePolicyInfoService;
import com.marvels.approve.manager.dto.OpinionDTO;
import com.marvels.approve.manager.service.impl.OpinionServiceImpl;
import com.marvels.approve.mqueues.service.ApproveLoanApplySynchronizeApi;
import com.marvels.approve.process.consum.ConsumerExternalFacesigApi;
import com.marvels.approve.process.dao.AttachmentInfoDao;
import com.marvels.approve.process.dao.ContractTemplateDao;
import com.marvels.approve.process.dao.IFaceSigAppointmentDao;
import com.marvels.approve.process.dao.IFaceSigOperationLogDao;
import com.marvels.approve.process.dao.ProtocolTemplateInfoDao;
import com.marvels.approve.process.dao.TaskProcessDao;
import com.marvels.approve.process.dto.FaceSigAppointmentDTO;
import com.marvels.approve.process.dto.FacesigOperationDTO;
import com.marvels.approve.process.dto.LaAttachmentDTO;
import com.marvels.approve.process.dto.McptManagementFeeDTO;
import com.marvels.approve.process.dto.McptProduct;
import com.marvels.approve.process.dto.McptProductFundRelationDto;
import com.marvels.approve.process.dto.ProtocolTemplateInfoDTO;
import com.marvels.approve.process.dto.SysUserDTO;
import com.marvels.approve.process.dto.SystemParamDTO;
import com.marvels.approve.process.service.IFaceCheckAssignmentService;
import com.marvels.approve.process.service.IFaceSigAppointmentService;
import com.marvels.approve.process.service.TaskProcessService;
import com.marvels.common.constants.FacesigOperationType;
import com.marvels.common.constants.LoanStateConstant;
import com.marvels.common.constants.MarvelsConstant;
import com.marvels.common.dto.ChannelUserDTO;
import com.marvels.common.dto.UserDTO;
import com.marvels.common.exception.MarvelsBusinessException;
import com.marvels.common.utils.CacheUtils;
import com.marvels.common.utils.ContractParseUtil;
import com.marvels.common.utils.DateUtils;
import com.marvels.common.utils.MarvelsLogUtil;
import com.marvels.common.utils.NumberUtils;
import com.marvels.common.utils.ServerProperties;
import com.marvels.common.utils.ThreadContextUtil;

import freemarker.template.TemplateException;
import net.sf.json.JSONObject;

@Service
public class FaceCheckAssignmentServiceImpl implements IFaceCheckAssignmentService{
    @Autowired
    private ConsumerExternalFacesigApi consumerExternalFacesigApi;
    @Autowired
    private ApproveConsumerExternalApi consumerExternalApi;
    @Autowired
    private ApproveConsumerUmApi consumerUmApi;
    @Autowired
   	private IFaceSigAppointmentService  faceSigAppointmentService;
    @Autowired
    private ProductConsumerService  productConsumerService;
	@Autowired
	private AttachmentInfoDao AttachmentInfoMapper;
    @Autowired
    private TaskProcessService  taskProcessService;
    @Autowired
  	private IFaceSigOperationLogDao iFaceSigOperationLogDao;
    @Autowired
	private TaskProcessDao taskProcessDao;
    @Autowired
    private ProtocolTemplateInfoDao ProtocolTemplateInfoMapper;
    @Autowired 
    private ApproveConsumerFinancialApi consumerFinancialApi;
	@Autowired
	private OpinionServiceImpl opinionService;
	@Autowired
	private ContractTemplateDao contractTemplateDao;
	@Autowired
	private ApproveConsumerProductApi consumerProductApi;
	@Autowired
	private McamLoanApplyInfoCommonService mcamLoanApplyInfoCommonService;
	@Autowired
	private IFaceSigAppointmentDao faceSigAppointmentDao;
	@Autowired
	private ApproveLoanApplySynchronizeApi loanApplySynchronizeApi;
	@Autowired
	private McamLoanInsurancePolicyInfoService mcamLoanInsurancePolicyInfoService;
	@Value("${config.properties.path}")
	private String filePath;
	
	@Override
	public McamLoanApplyInfoDTO searchCmAppCaseByLoanId(String loanId) throws MarvelsBusinessException {
		McamLoanApplyInfoDTO McamLoanApplyInfoDTO = taskProcessService.getLoanInfo(loanId);
        if(null==McamLoanApplyInfoDTO){
            throw new MarvelsBusinessException("该笔进件无法进行面签，因为还未生成工单!");
        }
        return McamLoanApplyInfoDTO;
	}
	/**
	 * 预览还款计划    --  取消
	 * @param loanId
	 * @return
	 * @throws MarvelsBusinessException 
	 */
	@Override
	public LoanAfterInfoDTO searchRepaymentPlan(String loanId) throws MarvelsBusinessException {
		McamLoanApplyInfoDTO loanApplyInfo= taskProcessDao.selectLoanApplyInfo(loanId);
		if(loanApplyInfo == null || "".equals(loanApplyInfo.getPrincipalAmt())){
			throw new MarvelsBusinessException("合同金额为空!");
		}
		LoanAfterInfoDTO  loanAfterInfo= new LoanAfterInfoDTO();
		loanAfterInfo.setDate(loanApplyInfo.getApplyTime());//贷款日期
		loanAfterInfo.setProductCode(loanApplyInfo.getProductCode());//产品类型
 		loanAfterInfo.setAmount(loanApplyInfo.getPrincipalAmt());//贷款金额
		loanAfterInfo.setTenor(loanApplyInfo.getApplyTerms());//期数
		loanAfterInfo = consumerFinancialApi.loanTrial(loanAfterInfo);
		return loanAfterInfo;
	}
	
	
	/**
	 * 查询面签操作记录
	 * @param loanId
	 * @return
	 */
	@Override
	public List<FacesigOperationDTO> selectFacesigOperationlog(String loanId) throws MarvelsBusinessException{
		return iFaceSigOperationLogDao.selectFacesigOperationlog(loanId);
	}
	
	/**
	 * 获取贷款金额
	 */
	@Override
	public Map<String,Object> searchAppAmount(String loanId,String appointmentId) throws MarvelsBusinessException{
		//查询核定金额
		McamLoanApplyInfoDTO  app= taskProcessService.getLoanInfo(loanId);
		DecimalFormat df = new DecimalFormat("#.00");
		//申请金额
		String applyeAmount = df.format(app.getPrincipalAmt()==null?BigDecimal.ZERO:app.getPrincipalAmt());
		//核定金额
		String amountStr = df.format(app.getPrincipalAmtAct()==null?BigDecimal.ZERO:app.getPrincipalAmtAct());
		String minAmonut = "0";
		
		
		McptProductTypeDto productTypeDto =  productConsumerService.getProductType(app.getProductCode());
		if(null!=productTypeDto && productTypeDto.getMinAmount()>0){
			//最低金额
			minAmonut = productTypeDto.getMinAmount().toString();
		}
		//获取合同模板
		List<ProtocolTemplateInfoDTO> protocolTemplateList = contractTemplateDao.findProtocalTemplateList(app);
		//带出操作记录
		List<FacesigOperationDTO> facesigOperates = this.selectFacesigOperationlog(loanId);
		//获取面签参数
		FaceSigAppointmentDTO  faceSigAppointmentDto  = faceSigAppointmentService.getRangeTime(appointmentId);
		
		Map<String,Object> amountMap = new HashMap<String,Object>();
		amountMap.put("appAmount", amountStr);
		amountMap.put("applyeAmount", applyeAmount);
		amountMap.put("minAmonut", minAmonut);
		amountMap.put("protocolTemplateList", protocolTemplateList);
		amountMap.put("facesigOperates", facesigOperates);
		amountMap.put("faceSigAppointmentDto", faceSigAppointmentDto);
		amountMap.put("waitTime", ServerProperties.getValue(filePath, "resource.properties", "visa.interview.wait.mins"));
		return amountMap;
	}
	
	private Map<String, String> resultYkdInfo(String mobileNum, String loanId) {
		Map<String, String> map = new HashMap<String, String>();
		// 手机号码(客户)
		SysUserDTO khUserInfo = consumerUmApi.queryUserByMobileNo(mobileNum, "2");
		map.put("userId", khUserInfo.getUserId() +"");
		String content="您的合同签署不通过，请重新签署。";  
		map.put("permeate", content);
		map.put("title", "产品视频签约提示");
		map.put("pushCategory", "1");
		map.put("messageCategory", "00006");
		map.put("loanId", loanId);
		map.put("targetUrl", "applyprogress");
		map.put("targetAlias", khUserInfo.getCid());//推送人id, 推送目标
		map.put("type", "2");
		return map;
	}
	
	private Map<String, String> resultYzyInfo(String custName, String userId,String loanId) {
		Map<String, String> map = new HashMap<String, String>();
		String content = "您的客户" + custName + "合同签署不通过，请提醒客户重新签署。";
		map.put("permeate", content);
		map.put("userId", userId);
		map.put("title", "产品视频签约提示");
		map.put("pushCategory", "2");
		map.put("messageCategory", "00009");
		map.put("loanId", loanId);
		map.put("targetUrl", "interview");
		map.put("type", "1");
		return map; 
	}
	
	/**
	 * 提交面谈结果  新增面谈/面签结果
	 * @param dto
	 * @param appointmentId
	 * @param type
	 * @return
	 * @throws MarvelsBusinessException 
	 */
	@Transactional(timeout = 30 ,rollbackFor = Exception.class)
	@Override
	public Integer addInterviewResult(FacesigOperationDTO dto) throws MarvelsBusinessException {
		UserDTO user = CacheUtils.getCacheUser();  //从缓存中读取到用户
		String userCode =user.getUserCode() == null?MarvelsConstant.SYSTEM_USER : user.getUserCode();
		Map<String,String> result = new HashMap<String,String>();
		Boolean type = dto.getType();
		String appointmentId = dto.getAppointmentId();
		if (StringUtils.equals(dto.getResultType(), FacesigOperationType.FACESIG)) {
			//面谈处理
			result = facesigDeal(dto,type);
		} else if (StringUtils.equals(dto.getResultType(), FacesigOperationType.INTERVIEW)) {
			//面签处理
			result = interviewDeal(dto,type,user);
		}
		//记录操作记录
		dto.setCreatedBy(userCode);
		dto.setUpdatedBy(userCode);
		
		String loanStatus = result.get("loanStatus");
		String signStatus = result.get("signStatus");
		if (!StringUtils.isEmpty(loanStatus)) {
			MarvelsLogUtil.getInstance().info("/*******************face check modify loan status start,the loanId is " + dto.getLoanId()+ ";the loanstatus is " + loanStatus);
			//修改贷款状态
			mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(dto.getLoanId(), loanStatus, null, userCode);
			MarvelsLogUtil.getInstance().info("*******************面签面谈更新贷款申请表状态完成：loanId----》"+dto.getLoanId()+"贷款状态：loanStatus----》"+loanStatus);

		}
		if (!StringUtils.isEmpty(signStatus)) {
			FaceSigAppointmentDTO faceSigAppointment = new FaceSigAppointmentDTO();
			faceSigAppointment.setId(Long.parseLong(appointmentId));
			faceSigAppointment.setFaceSigStatus(signStatus);
			faceSigAppointment.setRemark(dto.getRemark());
			faceSigAppointmentService.updateAppointment(faceSigAppointment,true);
			MarvelsLogUtil.getInstance().info("*******************面签面谈更新面签表完成：loanId----》"+dto.getLoanId()+"面签面谈状态：signStatus----》"+signStatus);
		}
		dto.setUpdatedBy(userCode);
		dto.setCreatedBy(userCode);
		dto.setAppointmentId(appointmentId);
		return iFaceSigOperationLogDao.insertFacesigOperationlog(dto);
	}
	/**
	 * 面谈处理
	 * @param dto
	 * @param type
	 */
	private Map<String,String> facesigDeal(FacesigOperationDTO dto,Boolean type) throws MarvelsBusinessException{
		String loanStatus = null;
		String signStatus = null;
		Map<String,String> result = new HashMap<String,String>();
		// 面谈不通过
		if (StringUtils.equals(dto.getResult(), FacesigOperationType.REJECT) && type) {
			loanStatus = LoanStateConstant.PR0;
			// 面谈否决
			signStatus = FacesigOperationType.REFUSED_TO_INTERVIEW;
			dto.setOperationContent("面谈拒绝");
		} else if (StringUtils.equals(dto.getResult(), FacesigOperationType.RETURN) && type) {
			// 面谈退回,该单进入到待预约面签状态
			loanStatus = LoanStateConstant.P01;
			// 面谈退回
			signStatus =  FacesigOperationType.INTERVIEW_BACK;
			// 面签退回消息推送
			McamLoanApplyInfoDTO loanApplyInfoDTO = taskProcessService.getLoanInfo(dto.getLoanId());
			String userId = loanApplyInfoDTO.getEmployeeId();
			Map<String,String> map = new HashMap<String,String>();
			map.put("loanId", dto.getLoanId());
			map.put("title", "面签退回提醒"); // 标题
			map.put("userId", userId); // 客户经理id
			map.put("type", "2"); // 推送消息类型
			Integer userid= null;
			userid = Integer.parseInt(userId == null ? "" : userId);
			MarvelsLogUtil.getInstance().info("method = getEntityByLoanId ===>" + userid);
			ChannelUserDTO usersys = consumerUmApi.queryUserById(Integer.parseInt(userId));
			if(usersys.getCid()==null){
				throw new MarvelsBusinessException("客户经理id为空");
			}
			map.put("targetAlias", usersys.getCid()); // 推送人id, 推送目标
			// 您的签名不符合相关要求，面签已被退回，需要重新签名
			map.put("permeate", "您名下的客户"+loanApplyInfoDTO.getCustName()+"在面谈环节被退回，请重新预约面谈!退回原因："+dto.getRemark()); // 推送内容
			map.put("targetUrl", "plan");
			map.put("messageCategory", "00009");
			//调用doubble  消息推送接口  
			String pushmsg = consumerExternalFacesigApi.pushFacePush(map);
			dto.setOperationContent("面谈退回");
			MarvelsLogUtil.getInstance().info("pushFacePush 消息推送结果===>" + pushmsg);
		} else if (StringUtils.equals(dto.getResult(), FacesigOperationType.PASS) && type) {
			// 面谈完成，该单进入视频面谈完成
			loanStatus = LoanStateConstant.P03;
			// 面谈通过
			signStatus = FacesigOperationType.INTERVIEW_BY;
			dto.setOperationContent("面谈通过");
		}else {
			signStatus = FacesigOperationType.HANG_UP;//挂起
		}
		result.put("loanStatus", loanStatus);
		result.put("signStatus", signStatus);
		return result;
	}
	/**
	 * 面签处理
	 * @param dto
	 * @param type
	 * @return
	 * @throws MarvelsBusinessException
	 */
	private Map<String,String> interviewDeal(FacesigOperationDTO dto,Boolean type,UserDTO user) throws MarvelsBusinessException{
		String loanStatus = null;
		String signStatus = null;
		Map<String,String> result = new HashMap<String,String>();
		// 如果是面签通过则修改贷款状态为签约完成确认
		if (StringUtils.equals(dto.getResult(), FacesigOperationType.PASS)) {
			// 判断用户是否已经完成电子签约
			String [] atmtTypeList = {"Q_MQ"};
			List<LaAttachmentDTO>   LaAttachmentList  = AttachmentInfoMapper.selectAttachmentInf(atmtTypeList, dto.getLoanId());
			
			if (StringUtils.equalsIgnoreCase("Y",ServerProperties.getValue(filePath, "resource.properties", "need.contract.sign.customer"))) {
				if (LaAttachmentList.isEmpty()) {
					throw new MarvelsBusinessException("客户还未完成电子协议签名，不允许提交为面签通过！");
				}
			}
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("loanId", dto.getLoanId());
			map.put("userId", user.getUserId());
			map.put("state", "1");
			// 新增合同状态信息表中的数据
			faceSigAppointmentDao.insertData(map);
			
			// 需APP确认放款
			loanStatus = LoanStateConstant.P05;
			
			McamLoanApplyInfoDTO app= taskProcessService.getLoanInfo(dto.getLoanId());//获取进件详情
			app.setIntoPoolTime(new Date());
			app.setUpdatedBy(user.getUserCode());
			//修改进件基础信息表中数据
			taskProcessDao.updateLoanInfo(app);
			// 面签通过
			signStatus = FacesigOperationType.HAS_SIGNED_FACE_TO;
			dto.setOperationContent("面签通过");
		} else if (StringUtils.equals(dto.getResult(), FacesigOperationType.REJECT)) {
			// 面签拒绝
			loanStatus = LoanStateConstant.PR0;
			signStatus = FacesigOperationType.SIGN_THE_REFUSED_TO_FACE_TO_FACE;
			dto.setOperationContent("面签拒绝");
		}
		result.put("loanStatus", loanStatus);
		result.put("signStatus", signStatus);
		return result;
	}
	/**
	 * 保存修改后的贷款金额
	 * @param dto
	 * @return
	 * @throws MarvelsBusinessException 
	 */
	@Transactional(timeout = 30 ,rollbackFor = Exception.class)
	@Override
	public Integer modifyCompactAmount(FacesigOperationDTO dto) throws MarvelsBusinessException {
		//获取合同金额
		McamLoanApplyInfoDTO  mcamLoanApplyInfoDTO =  taskProcessService.getLoanInfo(dto.getLoanId());
		BigDecimal applyAmt = mcamLoanApplyInfoDTO.getPrincipalAmtAct();//核定金额
		BigDecimal minAmonut = BigDecimal.ZERO;//最新金额
		McptProductTypeDto productTypeDto =  productConsumerService.getProductType(mcamLoanApplyInfoDTO.getProductCode());
		if(null!=productTypeDto && productTypeDto.getMinAmount()>0){
			//最低金额
			minAmonut = new BigDecimal(productTypeDto.getMinAmount());
		}
		BigDecimal oldAmout =mcamLoanApplyInfoDTO.getApplyAmount();
		BigDecimal newAmout = dto.getAmount();
		//校验
		if(newAmout.compareTo(applyAmt)==1){
			throw new MarvelsBusinessException("修改金额必须小于修改前核准金额!");
		}
		if(newAmout.compareTo(minAmonut)==-1){
			throw new MarvelsBusinessException("修改金额必须大于最小申请金额！");
		}
		MarvelsLogUtil.getInstance().info("*******************start modify compact amount,the loanId is "+dto.getLoanId()+";the old amount is "+applyAmt.toBigInteger().toString()+";the new amount is "+newAmout.toBigInteger().toString());
		UserDTO user = CacheUtils.getCacheUser();  //从缓存中读取到用户
		String userCode =user.getUserCode() == null?MarvelsConstant.SYSTEM_USER : user.getUserCode();
		mcamLoanApplyInfoDTO.setLoanId(dto.getLoanId());
		mcamLoanApplyInfoDTO.setPrincipalAmtAct(newAmout);
		mcamLoanApplyInfoDTO.setUpdatedBy(userCode);
		Integer flag = taskProcessDao.updateLoanStatus(mcamLoanApplyInfoDTO);
		if(flag > 0){
			//更新保单核定金额
			try {
				McamAcLoanApplyBdInfo insurancePolicyDto = new McamAcLoanApplyBdInfo();
				insurancePolicyDto.setLoanId(mcamLoanApplyInfoDTO.getLoanId());
				insurancePolicyDto.setInsuranceAmount(InsuranceRateUtil.getBxMoney(mcamLoanApplyInfoDTO));
				mcamLoanInsurancePolicyInfoService.updateAssureBx(insurancePolicyDto);
			} catch (Exception e) {
				MarvelsLogUtil.getInstance().error("更新保单异常！！！"+e);
				throw new MarvelsBusinessException("更新保单异常");
			}
			dto.setUpdatedBy(userCode);
			dto.setCreatedBy(userCode);
			dto.setOperationContent("合同金额由"+oldAmout.doubleValue()+"修改为"+newAmout.doubleValue());
			return iFaceSigOperationLogDao.insertFacesigOperationlog(dto);
		}else{
			throw new MarvelsBusinessException("修改贷款金额失败");
		}
	}
	/**
	 * 
	 * 预览贷款合同
	 * @param loanId
	 * @param templateNo
	 * @return
	 * @throws MarvelsBusinessException 
	 */
	@Override
	public Map<String,Object> previewLoanCompact(String loanId,String templateNo) throws MarvelsBusinessException {
		MarvelsLogUtil.getInstance().info("*******************开始执行合同预览loanId："+loanId+" 合同模板templateNo==>"+templateNo);
		//先查询线上还是线下
		McamLoanApplyInfoDTO mcamLoanApplyInfoDTO = taskProcessDao.selectLoanApplyInfo(loanId);
		McamLoanApplyInfoDTO acLoanInfoDto = null;
		McptProduct productTypeDTO=null;
		if(mcamLoanApplyInfoDTO==null){
			acLoanInfoDto = loanApplySynchronizeApi.queryLoanBasicInfo(loanId);
			if(acLoanInfoDto==null) throw new MarvelsBusinessException("对应的贷款不存在！======》》》》："+loanId);
			//查询产品类型
			productTypeDTO =  productConsumerService.getProduct(acLoanInfoDto.getProductCode() == null ? "0" : acLoanInfoDto.getProductCode());
		}else{
			//查询产品类型
			productTypeDTO =  productConsumerService.getProduct(mcamLoanApplyInfoDTO.getProductCode() == null ? "0" : mcamLoanApplyInfoDTO.getProductCode());
		}
		if( null == productTypeDTO || productTypeDTO.getProductType() == null || "".equals(productTypeDTO.getProductType())){
			throw new MarvelsBusinessException("产品类型为空!");
		}
		String patternType = productTypeDTO.getProductType();
		//定义资金源
		String fundSource = null;
		Integer terms = null;
		String productId = "";
		Map<String,Object>  result = new HashMap<String,Object>();
		if(StringUtils.equalsIgnoreCase(patternType, "A")){
			if(mcamLoanApplyInfoDTO==null){
				result = onLineProduct(acLoanInfoDto);
			}else{
				result = onLineProduct(mcamLoanApplyInfoDTO);
			}
			terms =(Integer) result.get("terms"); 
			productId =(String) result.get("productId"); 
		}else{	
			if(mcamLoanApplyInfoDTO==null) throw new MarvelsBusinessException("对应的贷款不存在！======》》》》："+loanId);
			//申请人姓名
			result.put("borrower",null==mcamLoanApplyInfoDTO.getCustName()?" ":mcamLoanApplyInfoDTO.getCustName());
			//申请人身份证编号
			result.put("borrowerCardId",null==mcamLoanApplyInfoDTO.getCustCardNo()? " " :mcamLoanApplyInfoDTO.getCustCardNo());
			//申请人地址
			result.put("borrowerAddress",null==mcamLoanApplyInfoDTO.getCurHomeAddress()?" ":mcamLoanApplyInfoDTO.getCurHomeAddress());
			//申请人电话
			result.put("borrowerCellPhnone", null==mcamLoanApplyInfoDTO.getMobileNo()?" ":mcamLoanApplyInfoDTO.getMobileNo());
			//还款卡号
			result.put("borrowerBankCardNo",null==mcamLoanApplyInfoDTO.getPaymentAcctNo()?" ":mcamLoanApplyInfoDTO.getPaymentAcctNo());
			//借款人邮编
			result.put("borrowerPostCode",null == mcamLoanApplyInfoDTO.getCompanyPost() ? " " :mcamLoanApplyInfoDTO.getCompanyPost());
			//借款还款账户开户名
			result.put("borrowerBankUserName",null==mcamLoanApplyInfoDTO.getPaymentAcctName()?" ":mcamLoanApplyInfoDTO.getPaymentAcctName());
			//借款人还款账户开户行名称
			result.put("borrowerBankName",null==mcamLoanApplyInfoDTO.getPaymentBankName()?" ":mcamLoanApplyInfoDTO.getPaymentBankName());
			//借款用途     描述
			result.put("loanUse",StringUtils.isEmpty(mcamLoanApplyInfoDTO.getPurpose())?" ":mcamLoanApplyInfoDTO.getPurpose());
			//核定金额大写
			result.put("loanCapitalUpper",null==mcamLoanApplyInfoDTO.getPrincipalAmtAct()?" ":NumberUtils.number2CNMontrayUnit(mcamLoanApplyInfoDTO.getPrincipalAmtAct()));
			//核定金额小写
			 result.put("loanCapitalLower", null==mcamLoanApplyInfoDTO.getPrincipalAmtAct()?" ":mcamLoanApplyInfoDTO.getPrincipalAmtAct());	
			//期数
			terms = mcamLoanApplyInfoDTO.getApplyTerms();
			//产品ID
			productId=mcamLoanApplyInfoDTO.getProductCode() == null ? " " : mcamLoanApplyInfoDTO.getProductCode();
			//资金源
			//fundCode;资金源ID',
			//fundName;'资金源',
			fundSource = mcamLoanApplyInfoDTO.getFundName();
		}
		//贷款期数
		result.put("ApplyTerms", terms);
		// 贷款限期：天数
		Date startDate = new Date();
		Date endDate = DateUtils.add(startDate, Calendar.MONTH, terms);
		int loanDays = (int) ((endDate.getTime() - startDate.getTime()) / 86400000);
		result.put("loanDays", loanDays);
		String [] atmtTypeList = {"Q_MQ"};
		List<LaAttachmentDTO>   laAttachmentList  = AttachmentInfoMapper.selectAttachmentInf(atmtTypeList, loanId);
		//获取签署合同图片时间    必须拿类型为Q_MQ的时间
		Date signDate = Calendar.getInstance().getTime();
		if(CollectionUtils.isNotEmpty(laAttachmentList)){
			signDate = laAttachmentList.get(0).getUploadTime();
		}
		
		//贷款发放Y-M-D日   --预计时间  当前时间+2天
		Date borrowIssueDate = DateUtils.add(signDate, Calendar.DAY_OF_MONTH, 2);
		String[] borrowIssueDateStr = DateUtils.getDateYYYY_MM_DD(borrowIssueDate).split("-");
		result.put("borrowIssueYear", borrowIssueDateStr[0]);
		result.put("borrowIssueMonth", borrowIssueDateStr[1]);
		result.put("borrowIssueDay", borrowIssueDateStr[2]);
		result.put("borrowIssueDate", DateUtils.getDateYYYY_MM_DD(borrowIssueDate));
		//贷款到期Y-M-D日  预计发放日月份+期数
		Date borrowExpireDate = DateUtils.add(borrowIssueDate, Calendar.MONTH, terms.intValue());
		String[] borrowExpireDateStr = DateUtils.getDateYYYY_MM_DD(borrowExpireDate).split("-");
		result.put("borrowExpireYear", borrowExpireDateStr[0]);
		result.put("borrowExpireMonth", borrowExpireDateStr[1]);
		result.put("borrowExpireDay", borrowExpireDateStr[2]);
		result.put("borrowExpireDate", DateUtils.getDateYYYY_MM_DD(borrowExpireDate));
		result.put("loanPeriod",12);
		
		String[] ymd = DateUtils.getDateYYYY_MM_DD(signDate).split("-");
		result.put("contractYear", ymd[0]);
		result.put("contractMonth", ymd[1]);
		result.put("contractDay", ymd[2]);
		
		//先查询是否已经有合同编号AcLoanApplyInfo
		McamLoanApplyInfoDTO  loanApplyInfo = taskProcessService.getLoanInfo(loanId);
		String compactCode = loanApplyInfo.getFjContractNo().toString();
		if(StringUtils.isEmpty(compactCode)){
			McamLoanApplyInfoDTO loandto = new McamLoanApplyInfoDTO();
			compactCode = "CT-XD-01-"+ymd[0]+ymd[1]+"-"+getCompactSeq();
			loandto.setFjContractNo(compactCode);
			loandto.setLoanId(loanId);
			taskProcessDao.updateLoanStatus(loandto);
		}
		result.put("compactCode", compactCode);
		//查询管理费
		McptManagementFeeDTO mcptManagementFeeDTO = productConsumerService.getMngfee(Long.parseLong(productTypeDTO.getManageFeeCode() == null ? "" : productTypeDTO.getManageFeeCode()));
		//管理费率
		double manageFee = mcptManagementFeeDTO.getPercentage().doubleValue();
		//如果资金源为空则到mp_fund_pricing中查找资金源（针对线上产品的，线下产品可能会人工改资金源,所以以AppConsumptionInst中为准）
		if(StringUtils.isEmpty(fundSource)){
			//查询产品资金源映射关系
			McptProductFundRelationDto mctp = new McptProductFundRelationDto();
			mctp.setProductCode(productId);
			List<McptProductFundRelationDto> prdtoList= productConsumerService.getProductFundingSource(mctp);//产品
			if(!CollectionUtils.isEmpty(prdtoList)){
				fundSource = prdtoList.get(0).getFundCode();
			}
		}
		MarvelsLogUtil.getInstance().info("*******************预览合同资金源为==>"+fundSource);
		String paramName = "FUND_SOURCE_" + fundSource + "_TERMS_" +terms;
		SystemParamDTO dto= new SystemParamDTO();
		dto.setParamName(paramName);
		List<SystemParamDTO> sysDtoList= AttachmentInfoMapper.selectParamConfig(dto);
		MarvelsLogUtil.getInstance().info(manageFee+"配置paramName:"+paramName);
		if (CollectionUtils.isNotEmpty(sysDtoList)) {
			//0.32%为0.0032
			String value="";
			for (SystemParamDTO systemParamDTO : sysDtoList) {
				value = systemParamDTO.getParamValue();
			}
			if (value == null) {
				value = "0";
			}
			BigDecimal tmFee = new BigDecimal(value);
			BigDecimal mFee = new BigDecimal(manageFee);
			manageFee = mFee.add(tmFee).doubleValue();
		}
		
		String managementFee = new BigDecimal(manageFee+"").multiply(new BigDecimal("100")).doubleValue()+"";
		result.put("managementFee", managementFee);
		//查询咨询费
		McptConsultingFeeDTO mcptConsultingFeeDTO = productConsumerService.getConsultingFee(Long.parseLong(productTypeDTO.getConsultingFeeCode() == null ? "" : productTypeDTO.getConsultingFeeCode()));
		String counselFee = (mcptConsultingFeeDTO.getPercentage().doubleValue()*100)+"";
		result.put("counselFee", counselFee);
		//查询利率编号
		McptProductFundRelationDto fundRelationDto = new McptProductFundRelationDto();
		fundRelationDto.setFundCode(mcamLoanApplyInfoDTO.getFundCode());
		fundRelationDto.setProductCode(mcamLoanApplyInfoDTO.getProductCode());
		List<McptProductFundRelationDto> fundList = consumerProductApi.selectProductFundRelation(fundRelationDto);
		BigDecimal rate = BigDecimal.ZERO;
		if(CollectionUtils.isNotEmpty(fundList)){
			rate= fundList.get(0).getRate();
			
		}
		//计算年利率
		String yearRate = (rate.doubleValue()*100)+"%";
		result.put("yearRate", yearRate);
		//xie
		String paramRate = "RATE_FUND_" + fundSource + "_" +productId; 
		MarvelsLogUtil.getInstance().info("配置paramRate:"+paramRate);
		dto.setParamName(paramRate);
		List<SystemParamDTO> rateList= AttachmentInfoMapper.selectParamConfig(dto);
		if(CollectionUtils.isNotEmpty(rateList)){
			String rateVal="";
			for (SystemParamDTO systemParamDTO : sysDtoList) {
				rateVal = systemParamDTO.getParamValue();
				break;
			}
			if (!StringUtils.isEmpty(rateVal)) {
				result.put("yearRate", rateVal);
			}
		}
		LoanAfterInfoDTO loanAfterInfoDTO= new LoanAfterInfoDTO();
		loanAfterInfoDTO.setTenor(terms);//期数
		loanAfterInfoDTO.setDate(new Date());
		loanAfterInfoDTO.setProductCode(productId);
		loanAfterInfoDTO.setAmount((BigDecimal)result.get("loanCapitalLower"));
		try{
			loanAfterInfoDTO = consumerFinancialApi.loanTrial(loanAfterInfoDTO);
			result.put("consultingFee", loanAfterInfoDTO.getAmount());// 借款金额
			result.put("aviAmount", loanAfterInfoDTO.getAviAmount());// 到手金额
			result.put("serviceFee", loanAfterInfoDTO.getManagementFee());// 管理费
			result.put("monthlyAmount", loanAfterInfoDTO.getMonthlyAmount());// 每月还款金额
		}catch(Exception ex){
			MarvelsLogUtil.getInstance().info("计算咨询费报错:loanId is "+loanId+" templateNo==>"+templateNo);
		}
		return getCompactHTML(result,templateNo);
	} 
	private Map<String,Object> onLineProduct(McamLoanApplyInfoDTO mcamLoanApplyInfoDTO){
		Map<String,Object>  result = new HashMap<String,Object>();
		//申请人姓名
		result.put("borrower",null==mcamLoanApplyInfoDTO.getCustName()?" ":mcamLoanApplyInfoDTO.getCustName());
		//申请人身份证编号
		result.put("borrowerCardId",null==mcamLoanApplyInfoDTO.getCustCardNo()?" ":mcamLoanApplyInfoDTO.getCustCardNo());
		//申请人地址
		result.put("borrowerAddress", null==mcamLoanApplyInfoDTO.getCustCardAddress()?" ":mcamLoanApplyInfoDTO.getCustCardAddress());
		//申请人电话
		result.put("borrowerCellPhnone", null==mcamLoanApplyInfoDTO.getMobileNo()?" ":mcamLoanApplyInfoDTO.getMobileNo());
		//还款卡号     
		result.put("borrowerBankCardNo",null==mcamLoanApplyInfoDTO.getPaymentAcctNo()?" ":mcamLoanApplyInfoDTO.getPaymentAcctNo());
		//借款人邮编
		result.put("borrowerPostCode",null == mcamLoanApplyInfoDTO.getCompanyPost() ? " " :mcamLoanApplyInfoDTO.getCompanyPost());
		//借款还款账户开户名
		result.put("borrowerBankUserName",null==mcamLoanApplyInfoDTO.getPaymentAcctName()?" ":mcamLoanApplyInfoDTO.getPaymentAcctName());
		//借款人还款账户开户行名称
		result.put("borrowerBankName",null==mcamLoanApplyInfoDTO.getPaymentBankName()?" ":mcamLoanApplyInfoDTO.getPaymentBankName());
		//借款用途     描述
		result.put("loanUse",StringUtils.isEmpty(mcamLoanApplyInfoDTO.getPurpose())? " " :mcamLoanApplyInfoDTO.getPurpose());	
		//核定金额大写
		result.put("loanCapitalUpper",null==mcamLoanApplyInfoDTO.getPrincipalAmtAct()?" ":NumberUtils.number2CNMontrayUnit(mcamLoanApplyInfoDTO.getPrincipalAmtAct()));
		//核定金额小写
		result.put("loanCapitalLower", null==mcamLoanApplyInfoDTO.getPrincipalAmtAct()?" ":mcamLoanApplyInfoDTO.getPrincipalAmtAct());	
		//期数
		result.put("terms", mcamLoanApplyInfoDTO.getApplyTerms());
		//产品ID
		result.put("productId", mcamLoanApplyInfoDTO.getProductCode() == null ? " " : mcamLoanApplyInfoDTO.getProductCode());
		return result;
	} 
	public Map<String,Object>  getCompactHTML(Map<String,Object> date,String templateNo) throws MarvelsBusinessException{
			MarvelsLogUtil.getInstance().info("/*******************previewLoanCompact the getCompactHTML is==>"+date + templateNo);
			//获取协议模板信息
			List<ProtocolTemplateInfoDTO> protocolTemplate = ProtocolTemplateInfoMapper.selectProtocolTemplte(Long.parseLong(templateNo));
			Map<String,Object> htmlData = new HashMap<String,Object>();
			try {
				String classPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
				for (ProtocolTemplateInfoDTO protocolTemplateInfoDTO : protocolTemplate) {
					String filePath = classPath+protocolTemplateInfoDTO.getTemplateFilePath();
					htmlData.put("htmlData", ContractParseUtil.parseContractTemplate(filePath, protocolTemplateInfoDTO.getTemplateFileName(), date));
					break;
				}
			} catch (IOException e) {
				MarvelsLogUtil.getInstance().info("转换贷款合同时未找到文件！");
				throw new MarvelsBusinessException("转换贷款合同时未找到文件",e);
			} catch (TemplateException e) {
				MarvelsLogUtil.getInstance().info("转换贷款合同时模板错误！");
				throw new MarvelsBusinessException("转换贷款合同时模板错误！",e);
			}
		return htmlData;
	}
	
	/**
	 * 发送合同
	 * @param loanId
	 * @return
	 * @throws MarvelsBusinessException 
	 **/
	@Transactional(timeout = 30 ,rollbackFor = Exception.class)
	@Override
	public Integer sendLoanCompact(String loanId,String isResend,String appointmentId,String returnCause) throws MarvelsBusinessException {
		MarvelsLogUtil.getInstance().info("*******************开始执行发送合同操作loanId："+loanId);
        FacesigOperationDTO operatdto = new FacesigOperationDTO();
        operatdto.setLoanId(loanId);
        operatdto.setResultType(FacesigOperationType.SEND_CONTRACT);
        operatdto.setOperationContent("发送签署电子合同短信");
        UserDTO user = CacheUtils.getCacheUser();  //从缓存中读取到用户
		String userCode =user.getUserCode() == null?MarvelsConstant.SYSTEM_USER : user.getOrgCode();
        //如果是重新发送贷款合同，将面签状态改为 面签退回	面签岗出具【重新发送电子协议】并提交——客户签字未返回
        if(StringUtils.equalsIgnoreCase("Y", isResend)){
        	operatdto.setResultType(FacesigOperationType.RESEND_CONTRACT);
        	operatdto.setOperationContent("重新发送签署电子合同短信");
        	operatdto.setRemark(returnCause);//设置退回原因
 			FaceSigAppointmentDTO faceSigAppointment = new FaceSigAppointmentDTO();
 			faceSigAppointment.setId(Integer.parseInt(appointmentId == null ? "" : appointmentId));
 			//面签退回
 			faceSigAppointment.setFaceSigStatus(FacesigOperationType.SIGN_THE_BACK_FACE_TO_FACE);
 			
 			MarvelsLogUtil.getInstance().info("*******************修改面签状态开始 appointmentId："+appointmentId+";状态为："+faceSigAppointment.getFaceSigStatus().toString());
 			faceSigAppointmentService.updateAppointment(faceSigAppointment,true);
 			MarvelsLogUtil.getInstance().info("*******************修改面签状态成功 the appointmentId："+appointmentId+";状态为："+faceSigAppointment.getFaceSigStatus().toString());
 			
 			mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(loanId, LoanStateConstant.P03, null, null);
 			
 			MarvelsLogUtil.getInstance().info("*******************重新发送签署电子合同时修改已签署的电子合同签字图片附件delete_flag字段  the loan id is ====>"+loanId);
 			McamAcLoanApplyImageInfo lattachmentdto = new McamAcLoanApplyImageInfo();
 			lattachmentdto.setLoanId(loanId);
 			lattachmentdto.setAtmtType("Q_MQ");
 			lattachmentdto.setUpdatedBy(userCode);
 			lattachmentdto.setDeleteFlag(1);
 			AttachmentInfoMapper.updateAttachmentStatus(lattachmentdto);
        }
        operatdto.setResult("01");
        operatdto.setCreatedBy(userCode);
        operatdto.setUpdatedBy(userCode);
        operatdto.setAppointmentId(appointmentId);
		iFaceSigOperationLogDao.insertFacesigOperationlog(operatdto);
		return null;
	}
	
	/**
	 * @throws MarvelsBusinessException *
	 * 修改预约面签状态
	 * @
	 */
	@Transactional(timeout = 30 ,rollbackFor = Exception.class)
	@Override
	public Integer modifyInterviewSignStatus(FaceSigAppointmentDTO dto) throws MarvelsBusinessException {
		//dto.getId() 面签流水中面签id
		MarvelsLogUtil.getInstance().info("/*******************modifyInterviewSignStatus start,the appointmentId is "+dto.getId()+";the FaceSigStatus is "+dto.getFaceSigStatus());
		Integer count=0;
		if(StringUtils.equalsIgnoreCase(FacesigOperationType.HAS_PASSED, dto.getFaceSigStatus())){
			//如果是已过号，需要将进件单状态修改为P01（待预约状态）
			mcamLoanApplyInfoCommonService.updateMcamLoanApplyInfoStatusByLoanId(dto.getLoanId(), LoanStateConstant.P01, null, null);
		}
		FaceSigAppointmentDTO faceSigAppointment = new FaceSigAppointmentDTO();
		faceSigAppointment.setId(dto.getId());
		faceSigAppointment.setFaceSigStatus(dto.getFaceSigStatus());
		count = faceSigAppointmentService.updateAppointment(faceSigAppointment,true);
		return count;
	}
	
	/**
	 * 获取合同编号
	 * @return
	 * @throws MarvelsBusinessException
	 */
	private Long getCompactSeq() throws MarvelsBusinessException {
		Long compactSeq= AttachmentInfoMapper.getCompactSeq();
		return compactSeq;
	}
	
//	private String getLoanCompact(String loanId,String compactType){
//		
//	}
	
//	@Override
//	public void setApplicationContext(ApplicationContext context) throws MarvelsBusinessException  {
//		// TODO Auto-generated method stub
//		//this.context=context;
//	}

	/**
	 * 重新签订合同
	 */
	@Override
	public Integer resetCompactSign(FacesigOperationDTO facesigOperationDTO,Boolean isNeedQueryUser) throws MarvelsBusinessException {
		MarvelsLogUtil.getInstance().info(">>>>>>>>>>>>>resetCompactSign>>>>>>>>>>loanId = "+facesigOperationDTO.getLoanId());
		McamLoanApplyInfoDTO applyInfo = taskProcessDao.selectLoanApplyInfo(facesigOperationDTO.getLoanId());
		if(applyInfo!=null && "A".equalsIgnoreCase(applyInfo.getPatternCode())){
			MarvelsLogUtil.getInstance().info("开始执行改p05状态=======》》》》："+applyInfo);
			//修改状态为P05
			taskProcessDao.updateLoanStatusToP05(facesigOperationDTO.getLoanId());
			MarvelsLogUtil.getInstance().info("执行改p05状态结束=======》》》》："+applyInfo);
		}
		return null;
	}
	/**
	 * 重新发送贷款合同，推送消息给云科贷，跟云展业
	 * @param loanId
	 */
	private void sendApplyInfo(String loanId) throws MarvelsBusinessException{
		//获取申请单的信息
		McamLoanApplyInfoDTO loanBasicInfo = taskProcessService.getLoanInfo(loanId);
		
		SysUserDTO user =consumerUmApi.queryUserByMobileNo(loanBasicInfo.getMobileNo(), "2");	
		//云科贷端推送内容，推送给客户的
		//手机号码
		String mobileNum = loanBasicInfo.getMobileNo();
		Map<String, String> ykdMap=resultYkdInfo(mobileNum, loanId);
		MarvelsLogUtil.getInstance().info("云科贷端推送内容如下ykdMap----："+ykdMap.toString());
		ykdMap.put("messageCategory", "00004");
		consumerExternalApi.pushFacePush(ykdMap);
		// 云展业端推送内容，推送给进件的客户经理或者团队长
		// 客户真实姓名
		String custName = loanBasicInfo.getCustName();
		Map<String, String> yzyMap=resultYzyInfo(custName, user.getUserId() + "", loanId);
		yzyMap.put("targetAlias", user.getCid());
		MarvelsLogUtil.getInstance().info("云展业端推送内容如下yzyMap----："+yzyMap.toString());
		yzyMap.put("messageCategory", "00010");
		consumerExternalApi.pushFacePush(yzyMap);
	}
	
	@Transactional(timeout = 30 ,rollbackFor=Exception.class)
	@Override
	public Map<String,Object> getTemplateHTML(String loanId, String templateNo) throws MarvelsBusinessException {
		McamLoanApplyInfoDTO loanApplyInfo = taskProcessService.getLoanInfo(loanId);
		String [] AtmtType ={"Q"};
		List<LaAttachmentDTO>   attachmentList  = AttachmentInfoMapper.selectAttachmentInf(AtmtType,loanId);
//		String html = "无协议信息";
		Map<String,Object> dataMap = new HashMap<String, Object>();
		//申请人姓名
		dataMap.put("borrower", loanApplyInfo.getCustName());
		//申请人身份证编号
		dataMap.put("borrowerCardId",loanApplyInfo.getCustCardNo());
		String[] ymd = DateUtils.getDateYYYY_MM_DD(attachmentList.get(0).getUploadTime()).split("-");
		dataMap.put("contractYear", ymd[0]);
		dataMap.put("contractMonth", ymd[1]);
		dataMap.put("contractDay", ymd[2]);
		
		//先查询是否已经有合同编号AcLoanApplyInfo     compact_code
		//List<LaAttachmentDTO>   attachmentList2  = AttachmentInfoService.selectAttachmentInf(laAttachmentDTO);
		String compactCode = loanApplyInfo.getCompanyCode();
		if(StringUtils.isEmpty(compactCode)){
			compactCode = "CT-XD-01-"+ymd[0]+ymd[1]+"-"+getCompactSeq();
			loanApplyInfo.setLoanId(loanId);
			loanApplyInfo.setCompanyCode(compactCode);
			taskProcessDao.updateLoanStatus(loanApplyInfo);
			
		}
		//external_contract
		dataMap.put("compactCode", compactCode);
		//String externalContract = loanApplyInfo.getExternalContract();
//		String externalContract = loanApplyInfo.getExternalContract();
//		if(externalContract!= null && !"".equals(externalContract.trim())){
//			dataMap.put("externalContract", externalContract);
//		}else{
//			dataMap.put("externalContract", "");
//		}
		return getCompactHTML(dataMap,templateNo);
	}
	/**
	 * 查询日志记录
	 */
	@Override
	public List<OpinionDTO> queryLoanApplyCaseLogs(String loanId) throws MarvelsBusinessException{
		OpinionDTO dto = new OpinionDTO();
		dto.setLoanId(loanId);
		return  opinionService.findOpinions(dto);
	}
	
}